module expd.tree;
import expd.node;
import expd.itree;
import expd.except :
TreeBuildingEException;
import expd.comp;
import _ver = expd._version;
//help wanted here
version(dbg3)
{
    import expd.meta;
    mixin (DebugTrick());
}
class ETree(T) : ITree!T, _ver.Versionable
{
    alias node!T Node;
    Node base;
    Node* curnode;

    this()
    {
        base.up = null;
        curnode = &base;
    }

    ref Node getNode()
    {
        return *curnode;   //find a better way
    }

    ref Node getBase()
    {
        return base;
    }
    void select(size_t x)
    {
        if(curnode.nb < (x+1)) throw new TreeBuildingEException("Out of bonds element");
        if(x == 0)
        {
            curnode = curnode.down;
            return;
        };
        curnode = search(curnode,x);
        if(curnode is null) throw new TreeBuildingEException("FAIL: null reference in tree");
    }

    void selectLast()
    {
        curnode = curnode.last;
    }

    Node * search(Node* pat,size_t x)
    {
        Node* res = pat.down;
        for(size_t i = 0; (i)<x; i++)
        {
            res = res.next;
        }
        if(res is null) throw new TreeBuildingEException("FAIL: null reference in tree");
        return res;
    }

    void add(ref Node xa)
    {
        Node* x = void;
        x = cast(Node*) (dmalloc(Node.sizeof)); //Force a copy
        *x = xa;
        x.up = curnode;
        if(curnode.nb == 0)
        {
            curnode.down = x;
        }
        else
        {
            curnode.last.next = x;
        }
        curnode.last = x;
        curnode.nb++;
    }

    void up()
    {
        curnode = curnode.up;
    }
    string nodest(Node* n)
    {
        if(n is null) return "X";
        if(n == n.next) return "("~to_string(*n)~")["~nodest(n.down)~"]&self ";
        return "("~to_string(*n)~")["~nodest(n.down)~"] , "~nodest(n.next);
    }
    override string toString()
    {
        return nodest(&base);
    }
    mixin(_ver.genVersion!(1,0,0));
}
